﻿using System;
using System.Threading;
using Object = UnityEngine.Object;

namespace MLog.Core {
    public abstract class BaseLogger : ILogger {
        public string Name { get; set; }
        public LogLevel Level { get; set; }

        public void Error(string message) {
            LogFormat(LogLevel.Error, null, null, message);
        }

        public void Error(string message, params object[] args) {
            LogFormat(LogLevel.Error, null, null, message, args);
        }

        public void Error(Exception exception, string message, params object[] args) {
            LogFormat(LogLevel.Error, exception, null, message, args);
        }

        public void Error(Object context, string message, params object[] args) {
            LogFormat(LogLevel.Error, null, context, message, args);
        }

        public void Error(Exception exception, Object context, string message, params object[] args) {
            LogFormat(LogLevel.Error, exception, context, message, args);
        }

        public void Warning(string message) {
            LogFormat(LogLevel.Warning, null, null, message);
        }

        public void Warning(string message, params object[] args) {
            LogFormat(LogLevel.Warning, null, null, message, args);
        }

        public void Warning(Exception exception, string message, params object[] args) {
            LogFormat(LogLevel.Warning, exception, null, message, args);
        }

        public void Warning(Object context, string message, params object[] args) {
            LogFormat(LogLevel.Warning, null, context, message, args);
        }

        public void Warning(Exception exception, Object context, string message, params object[] args) {
            LogFormat(LogLevel.Warning, exception, context, message, args);
        }

        public void Info(string message) {
            LogFormat(LogLevel.Info, null, null, message);
        }

        public void Info(string message, params object[] args) {
            LogFormat(LogLevel.Info, null, null, message, args);
        }

        public void Info(Exception exception, string message, params object[] args) {
            LogFormat(LogLevel.Info, exception, null, message, args);
        }

        public void Info(Object context, string message, params object[] args) {
            LogFormat(LogLevel.Info, null, context, message, args);
        }

        public void Info(Exception exception, Object context, string message, params object[] args) {
            LogFormat(LogLevel.Info, exception, context, message, args);
        }

        public void Debug(string message) {
            LogFormat(LogLevel.Debug, null, null, message);
        }

        public void Debug(string message, params object[] args) {
            LogFormat(LogLevel.Debug, null, null, message, args);
        }

        public void Debug(Exception exception, string message, params object[] args) {
            LogFormat(LogLevel.Debug, exception, null, message, args);
        }

        public void Debug(Object context, string message, params object[] args) {
            LogFormat(LogLevel.Debug, null, context, message, args);
        }

        public void Debug(Exception exception, Object context, string message, params object[] args) {
            LogFormat(LogLevel.Debug, exception, context, message, args);
        }

        public bool IsLogTypeAllowed(LogLevel level) {
            return level >= Level && level != LogLevel.None;
        }

        private void LogFormat(LogLevel level, Exception exception, Object context, string message,
            params object[] args) {
            if (IsLogTypeAllowed(level)) {
                var @event = LoggerEvent.Obtain(this, Thread.CurrentThread.Name, DateTime.Now,
                    level, exception, context, message, args);
                LogEvent(@event);
                @event.Recycle();
            }
        }

        public abstract void LogEvent(LoggerEvent @event);
    }
}